#pragma once

#include <AVUIFrameworkElement.h>
#include <AVUIVisualCollection.h>

namespace AVUI {

class Adorner;
class GeneralTransform;

class AdornerLayer : public FrameworkElement
{
public:
    DECLARE_ELEMENT(AdornerLayer, FrameworkElement);

	AdornerLayer();
	~AdornerLayer();

	static AdornerLayer* GetAdornerLayer(Visual* pVisual);

	void Add(Adorner* pAdorner, int zOrder = c_defaultZOrder); 
	void Remove(Adorner* pAdorner);

	virtual int get_VisualChildrenCount() { return m_children.get_Count(); }
	virtual Visual* GetVisualChild(int idx) { return m_children[idx]; }

protected:

	virtual Size MeasureOverride(const Size& constraintSize);
	virtual Size ArrangeOverride(const Size& constraintSize);

private:
	static const int c_defaultZOrder = 0x7FFFFFFF;
	class AdornerInfo : public Object
	{
	public:
		AdornerInfo(Adorner* pAdorner) { m_pAdorner = pAdorner; }

		Adorner* get_Adorner() { return m_pAdorner; }

		Size get_RenderSize() { return m_renderSize; }
		void set_RenderSize(const Size& renderSize) { m_renderSize = renderSize; }

		GeneralTransform* get_Transform() { return m_pTransform; }
		void set_Transform(GeneralTransform* pTransform) { m_pTransform = pTransform; }

		int get_ZOrder() { return m_zOrder; }
		void set_ZOrder(int zOrder) { m_zOrder = zOrder; }

	private:
		TRefCountedPtr<Adorner> m_pAdorner;
		Size m_renderSize;
		TRefCountedPtr<GeneralTransform> m_pTransform;
		int m_zOrder;
	};

	struct ElementEntry
	{
		TRefCountedPtr<UIElement> pElement;
		ItemStructList< TRefCountedPtr<AdornerInfo> > rgAdorners;
	};

	// Deviation here, WPF uses interfaces to anonymize zorder map and element map. We duplicate the methods, zOrder is not supported for now
	void AddAdornerInfoToElementMap(AdornerInfo* pAdornerInfo, UIElement* pElement);
	void AddAdornerToVisualTree(AdornerInfo* pAdornerInfo, int zOrder);
	void UpdateAdorner(UIElement* pElement);
	ItemStructList< TRefCountedPtr<AdornerInfo> >* GetElementMapValue(UIElement* pElement);
	AdornerInfo* GetAdornerInfo(ItemStructList< TRefCountedPtr<AdornerInfo> >* pAdorners, Adorner* pAdorner);
	bool RemoveAdornerInfoFromElementMap(Adorner* pAdorner, UIElement* pElement);
	void Clear(UIElement* pElement);
	void UpdateElementAdorners(UIElement* pElement);
	void InvalidateAdorner(AdornerInfo* pAdornerInfo);
	TRefCountedPtr<GeneralTransform> GetProposedTransform(Adorner* pAdorner, GeneralTransform* pSourceTransform);
	void OnLayoutUpdated(Object* pSender, EventArgs* pArgs);

	VisualCollection m_children;
	ItemStructList<ElementEntry> m_elementMap;
};

}; // namespace AVUI


